<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/4/14
 * Time: 0:03
 */
namespace App\libraries;

/**
 * 七牛API
 */

 class qiniuApi
{
    private static $ak = '';
    private static $sk = '';

    /**
     * 安全的base64编码
     */
    private static function safeBase64Encode($str)
    {
        $find = array("+", "/");
        $replace = array("-", "_");
        return str_replace($find, $replace, base64_encode($str));
    }

    /**
     * 安全的base64解码
     */
    private static function safeBase64Decode($str)
    {
        $find = array("-", "_");
        $replace = array("+", "/");
        return base64_decode(str_replace($find, $replace, $str));
    }

    private static function hmac_sha1($str, $key)
    {
        return hash_hmac("sha1", $str, $key, true);
    }

    /**
     * 管理凭证
     * @param $url 要上传的URL
     * @param $body POST时的内容
     */
    private static function getAccessToken($url, $body = array())
    {
        $urlInfo = parse_url($url);
        $signingStr = $urlInfo['path'];
        if(!empty($urlInfo['query']))
        {
            $signingStr .= '?' . $urlInfo['query'];
        }
        $signingStr .= "\n";

        if(!empty($body))
        {
            $signingStr .= http_build_query($body);
        }

        $sign = self::safeBase64Encode(self::hmac_sha1($signingStr, self::$sk));
        $accessToken = self::$ak . ":" . $sign;

        return $accessToken;
    }

    /**
     * 上传文件(非视频)凭证
     */
    public static function getUploadFileToken($scope, $extTime = 43200, $returnUrl = '', $callbackUrl = '')
    {
        $policy = array();
        $policy['scope'] = $scope;
        $policy['deadline'] = time() + $extTime;

        $body = array();
        $body['key'] = '$(key)';
        $body['name'] = '$(fname)';
        $body['size'] = '$(fsize)';
        $body['mime'] = '$(mimeType)';
        $body['suffix'] = '$(suffix)';
        $body['hash'] = '$(etag)';
        $body['width'] = '$(imageInfo.width)';
        $body['height'] = '$(imageInfo.height)';


        if(!empty($returnUrl))
        {
            $body['exif'] = '$(exif)';
            $body['imageInfo'] = '$(imageInfo)';
            $body['imageAve'] = '$(imageAve)';
        }

        if(!empty($callbackUrl))
        {
            $body['exif'] = '$(exif)';
            $body['imageInfo'] = '$(imageInfo)';
            $body['imageAve'] = '$(imageAve)';

            $policy['callbackUrl'] = $callbackUrl;
            $policy['callbackBody'] = json_encode($body);
        }
        else
        {
            $policy['returnUrl'] = $returnUrl;
            $policy['returnBody'] = json_encode($body);
        }

        $putPolicy = self::safeBase64Encode(json_encode($policy));
        $sign = self::safeBase64Encode(self::hmac_sha1($putPolicy, self::$sk));
        $uploadToken = self::$ak . ':' . $sign . ':' . $putPolicy;

        return $uploadToken;
    }

    /**
     * 视频上传凭证
     * markPos位置:
     * NorthWest	|	North	|	NorthEast
     * West		|	Center	|	East
     * SouthWest	|	South	|	SouthEast
     */
    public static function getUploadMediaToken($scope, $extTime = 43200, $notifyUrl, $mark = '', $markPos = 'NorthEast')
    {
        $policy = array();
        $policy['scope'] = $scope;
        $policy['deadline'] = time() + $extTime;

        $ops = array();
        if(!empty($mark))
        {
            $ops[] = 'avthumb/mp4/wmImage/' . self::safeBase64Encode($mark) . '/Gravity/' . $markPos;		//转码成MP4
            $ops[] = 'avthumb/m3u8/preset/video_1000k/wmImage/' . self::safeBase64Encode($mark) . '/Gravity/' . $markPos;	//转码成M3U8
        }
        else
        {
            $ops[] = 'avthumb/mp4';
            $ops[] = 'avthumb/m3u8/preset/video_1000k';
        }

        $policy['persistentOps'] = implode(';', $ops);
        $policy['persistentNotifyUrl'] = $notifyUrl;

        $putPolicy = self::safeBase64Encode(json_encode($policy));
        $sign = self::safeBase64Encode(self::hmac_sha1($putPolicy, self::$sk));
        $uploadToken = self::$ak . ':' . $sign . ':' . $putPolicy;

        return $uploadToken;
    }

    /**
     * 下载凭证(私有空间时使用)
     */
    public static function getDownloadToken($url, $extTime = 43200)
    {
        $e = 'e=' . (time() + $extTime);
        if(preg_match('/\?/ism', $url))
        {
            $url .= '&' . $e;
        }
        else
        {
            $url .= '?' . $e;
        }

        $sign = self::safeBase64Encode(self::hmac_sha1($url, self::$sk));
        $downloadToken = self::$ak . ":" . $sign;
        //$realDownloadUrl = $url . '&token=' . $downloadToken;

        return $e . '&token=' . $downloadToken;
    }

    /**
     * 查询处理状态
     */
    public static function getPersistentInfo($persistentID)
    {
        $url = 'http://api.qiniu.com/status/get/prefop?id=' . $persistentID;

        $html = Http::request(array('url' => $url));
        $json = json_decode($html['html'], true);
        if(empty($json['code']))
        {
            return array();
        }
        else
        {
            return $json;
        }
    }

    /**
     * 触发式音视频转换
     * 水印:avthumb/wmImage/safeBase64Encode(image url)/Gravity/位置
     * 位置:
     * NorthWest	|	North	|	NorthEast
     * West		|	Center	|	East
     * SouthWest	|	South	|	SouthEast
     */
    public static function convertMedia($scope, $key, $notifyUrl, $mark = '', $markPos = 'NorthEast')
    {
        $url = "http://api.qiniu.com/pfop/";

        $ops = array();
        if(!empty($mark))
        {
            $ops[] = 'avthumb/mp4/wmImage/' . self::safeBase64Encode($mark) . '/Gravity/' . $markPos;		//转码成MP4
            $ops[] = 'avthumb/m3u8/preset/video_1000k/wmImage/' . self::safeBase64Encode($mark) . '/Gravity/' . $markPos;	//转码成M3U8
        }
        else
        {
            $ops[] = 'avthumb/mp4';
            $ops[] = 'avthumb/m3u8/preset/video_1000k';
        }

        $data = array();
        $data['bucket'] = $scope;
        $data['key'] = $key;
        $data['fops'] = implode(';', $ops);
        $data['notifyURL'] = $notifyUrl;

        $accessToken = self::getAccessToken($url, $data);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'data' => $data, 'httpheader' => $header));
        $json = json_decode($html['html'], true);
        if(empty($json['persistentId']))
        {
            return '';
        }
        else
        {
            return $json['persistentId'];
        }
    }

    /**
     * 视频截图
     * 截图:vframe/(jpg|png)/offset/秒数/w/宽/h/高/rotate/旋转(空|90|180|270|auto)
     */
    public static function getVideoImage($scope, $key, $notifyUrl, $second, $width, $height, $rotate = '')
    {
        $url = "http://api.qiniu.com/pfop/";

        $data = array();
        $data['bucket'] = $scope;
        $data['key'] = $key;

        $data['fops'] = sprintf('vframe/jpg/offset/%s/w/%s/h/%s', $second, $width, $height);
        if(!empty($rotate))
        {
            $data['fops'] .= $data['fops'] . '/rotate/' . $rotate;
        }

        $data['notifyURL'] = $notifyUrl;

        $accessToken = self::getAccessToken($url, $data);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'data' => $data, 'httpheader' => $header));
        //http://api.qiniu.com/status/get/prefop?id=53b05821c868fc3b200498ba
        $json = json_decode($html['html'], true);
        if(empty($json['persistentId']))
        {
            return '';
        }
        else
        {
            return $json['persistentId'];
        }
    }

    /**
     * 得到音视频信息
     */
    public static function getMediaInfo($scope, $key, $private = false, $extTime = 3600)
    {
        if(preg_match('/\?/ism', $url))
        {
            $url = 'http://' . $scope . '.qiniudn.com/' . $key . '&avinfo';
        }
        else
        {
            $url = 'http://' . $scope . '.qiniudn.com/' . $key . '?avinfo';
        }

        if($private)
        {
            $url .= '&' . self::getDownloadToken($url, $extTime);
        }

        $html = Http::request(array('url' => $url));
        $json = json_decode($html['html'], true);

        if(empty($json['streams']))
        {
            return array();
        }
        else
        {
            return $json;
        }
    }

    /**
     * 得到图片信息
     */
    public static function getImageInfo($scope, $key, $private = false, $extTime = 120)
    {
        $url = 'http://' . $scope . '.qiniudn.com/' . $key . '?imageInfo';

        if($private)
        {
            $url .= '&' . self::getDownloadToken($url, $extTime);
        }

        $html = Http::request(array('url' => $url));
        $json = json_decode($html['html'], true);
        if(empty($json['format']))
        {
            return array();
        }
        else
        {
            return $json;
        }
    }

    /**
     * 得到图片Exif
     */
    public static function getImageExif($scope, $key, $private = false, $extTime = 120)
    {
        $url = 'http://' . $scope . '.qiniudn.com/' . $key . '?exif';

        if($private)
        {
            $url .= '&' . self::getDownloadToken($url, $extTime);
        }

        $html = Http::request(array('url' => $url));
        $json = json_decode($html['html'], true);
        if(empty($json['error']))
        {
            return $json;
        }
        else
        {
            return array();
        }
    }

    /**
     * 得到图片主颜色(RGB值)
     */
    public static function getImageRGB($scope, $key, $private = false)
    {
        $url = 'http://' . $scope . '.qiniudn.com/' . $key . '?imageAve';
        if($private)
        {
            $url .= '&' . self::getDownloadToken($url);
        }

        $html = Http::request(array('url' => $url));
        $json = json_decode($html['html'], true);
        if(empty($json['RGB']))
        {
            return '';
        }
        else
        {
            return $json['RGB'];
        }
    }

    /**
     * 得到缩略图片地址
     * @param $imageParam
     * array('width' => 100,
     *	'height' => 100,
     *	'format' => '',
     *	'crop_type' => 'Center',
     *	'crop_width' => '',
     *	'crop_height' => '',
     *	'rotate' => '',
     *	'blur' => '3x5',
     *	'mark_url' => '',
     *	'mark_type' => '',
     *	'mark_dissolve' => '')
     * 参数说明:
     * width,height	当某一项为0时,以另一个为主
     * format	指定输出格式:空为原图格式,jpg,gif,png,webp
     * crop_type	是否进行裁剪,如果要进行裁剪,则width和height不能为0
     * crop_type取值:
     * NorthWest	|	North	|	NorthEast
     * West		|	Center	|	East
     * SouthWest	|	South	|	SouthEast
     *
     * crop_width,crop_height	当需要进行裁剪时,必需填写此两个值
     * rotate	旋转,取值:1-360
     * blur		高斯模糊,取值:1-50
     */
    public static function getImageZoomUrl($scope, $key, $imageParam = array(), $private = false, $extTime = 43200)
    {
        $url = 'http://' . $scope . '.qiniudn.com/' . $key . '?imageMogr2/auto-orient/strip/thumbnail';

        if(isset($imageParam['width']) && !empty($imageParam['width']))
        {
            //正比例缩放
            $url .= '/' . $imageParam['width'] . 'x';
        }

        if(isset($imageParam['height']) && !empty($imageParam['height']))
        {
            //正比例缩放
            if(substr($url, strlen($url) - 1, 1) == 'x')
            {
                $url .= $imageParam['height'];
            }
            else
            {
                $url .= '/x' . $imageParam['height'];
            }
        }

        if(isset($imageParam['format']) && !empty($imageParam['format']))
        {
            //设置输出格式
            $url .= '/format/' . $imageParam['format'];

            //如果输出为jpg格式,则设置渐进显示模式
            if($imageParam['format'] == 'jpg')
            {
                $url .= '/interlace/1';
            }
        }

        if(isset($imageParam['rotate']) && !empty($imageParam['rotate']))
        {
            //设置旋转
            $url .= '/rotate/' . $imageParam['rotate'];
        }

        if(isset($imageParam['blur']) && !empty($imageParam['blur']))
        {
            //设置模糊
            $url .= '/blur/' . $imageParam['blur'];
        }

        if(isset($imageParam['crop_type']) && !empty($imageParam['crop_type']))
        {
            //设置裁剪模式
            $url .= '/gravity/' . $imageParam['crop_type'] . '/crop';

            if(isset($imageParam['crop_width']) && !empty($imageParam['crop_width']))
            {
                //正比例缩放
                $url .= '/' . $imageParam['crop_width'] . 'x';
            }

            if(isset($imageParam['crop_height']) && !empty($imageParam['crop_height']))
            {
                //正比例缩放
                if(substr($url, strlen($url) - 1, 1) == 'x')
                {
                    $url .= $imageParam['crop_height'];
                }
                else
                {
                    $url .= '/x' . $imageParam['crop_height'];
                }
            }
        }

        if(isset($imageParam['mark_url']) && !empty($imageParam['mark_url']))
        {
            //打水印
            $url .= '|watermark/1/image/' . self::safeBase64Encode($imageParam['mark_url']);

            if(isset($imageParam['mark_dissolve']) && !empty($imageParam['mark_dissolve']))
            {
                //透明度
                $url .= '/dissolve/' . $imageParam['mark_dissolve'];
            }

            if(isset($imageParam['mark_type']) && !empty($imageParam['mark_type']))
            {
                //水印位置
                $url .= '/gravity/' . $imageParam['mark_type'];
            }
        }

        if($private)
        {
            $url .= '&' . self::getDownloadToken($url, $extTime);
        }

        return $url;
    }

    /**
     * 得到链接
     */
    public static function getUrl($scope, $key, $private = false, $extTime = 43200)
    {
        $url = 'http://' . $scope . '.qiniudn.com/' . $key;
        if($private)
        {
            $url .= '?' . self::getDownloadToken($url, $extTime);
        }

        return $url;
    }

    /**
     * 抓取资源
     */
    public static function fetchUrl($scope, $key, $url)
    {
        $fileName = self::safeBase64Encode($scope . ':' . $key);
        $fetchUrl = self::safeBase64Encode($url);
        $url = 'http://iovip.qbox.me/fetch/' . $fetchUrl . '/to/' . $fileName;

        $accessToken = self::getAccessToken($url);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'httpheader' => $header, 'timeout' => 60));
        $json = json_decode($html['html'], true);
        if(empty($json))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * 删除资源
     */
    public static function delKey($scope, $key)
    {
        $fileName = self::safeBase64Encode($scope . ':' . $key);

        $url = 'http://rs.qiniu.com/delete/' . $fileName;

        $accessToken = self::getAccessToken($url);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'httpheader' => $header, 'timeout' => 60));
        $json = json_decode($html['html'], true);
        if(empty($json))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * 移动资源
     */
    public static function moveKey($scopeSrc, $keySrc, $scopeDest, $keyDest)
    {
        $keySrc = self::safeBase64Encode($scopeSrc . ':' . $keySrc);
        $keyDest = self::safeBase64Encode($scopeDest . ':' . $keyDest);

        $url = 'http://rs.qiniu.com/move/' . $keySrc . '/' . $keyDest;

        $accessToken = self::getAccessToken($url);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'httpheader' => $header, 'timeout' => 60));
        $json = json_decode($html['html'], true);
        if(empty($json))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * 复制资源
     */
    public static function copyKey($scopeSrc, $keySrc, $scopeDest, $keyDest)
    {
        $keySrc = self::safeBase64Encode($scopeSrc . ':' . $keySrc);
        $keyDest = self::safeBase64Encode($scopeDest . ':' . $keyDest);

        $url = 'http://rs.qiniu.com/copy/' . $keySrc . '/' . $keyDest;

        $accessToken = self::getAccessToken($url);

        $header = array();
        $header[] = 'Authorization: QBox ' . $accessToken;

        $html = Http::request(array('url' => $url, 'httpheader' => $header, 'timeout' => 60));
        $json = json_decode($html['html'], true);
        if(empty($json))
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    /**
     * 上传文件(直传)
     */
    public static function uploadFile($scope, $key, $fileName, $extTime = 86400, $notifyUrl = '')
    {
        $data = array();
        if(empty($notifyUrl))
        {
            $data['token'] = self::getUploadFileToken($scope, $extTime);
        }
        else
        {
            $data['token'] = self::getUploadMediaToken($scope, $extTime, $notifyUrl);
        }
        $data['filename'] = basename($fileName);
        $data['file'] = '@' . $fileName;
        $data['key'] = $key;
        $data['upload_file'] = true;

        $html = Http::request(array('url' => 'http://up.qiniu.com', 'data' => $data, 'timeout' => 5 * 60));
        print_r($html);
        $json = json_decode($html['html'], true);
        if(empty($json['key']))
        {
            return array();
        }
        else
        {
            if(empty($notifyUrl))
            {
                $json['name'] = basename($fileName);
                return $json;
            }
            else
            {
                return array('persistentId' => $json['persistentId']);
            }
        }
    }

    /**
     * 文件上传(分片)
     */
    public static function uploadFileSplit($scope, $key, $file, $extTime = 86400, $notifyUrl = '')
    {
        $fileSize = 0;
        $ctxInfo = array();

        $host = 'http://up.qiniu.com';

        $header = array();
        if(empty($notifyUrl))
        {
            $header[] = 'Authorization: UpToken ' . self::getUploadFileToken($scope, $extTime);
        }
        else
        {
            $header[] = 'Authorization: UpToken ' . self::getUploadMediaToken($scope, $extTime, $notifyUrl);
        }

        $fp = fopen($file, 'rb');
        while(!feof($fp))
        {
            $data = fread($fp, 4194304);	//4194304为4M的字节数 4 * 1024 * 1024

            $fileSize += strlen($data);

            $url = $host . '/mkblk/' . strlen($data);
            $html = Http::request(array('url' => $url, 'data' => $data, 'timeout' => 5 * 60, 'httpheader' => $header));
            $json = json_decode($html['html'], true);
            if(empty($json['crc32']))
            {
                return array();
            }
            else
            {
                $ctxInfo[] = $json['ctx'];
                $host = $json['host'];
            }
        }

        $ctxData = implode(',', $ctxInfo);

        $url = $host . '/mkfile/' . $fileSize . '/key/' . self::safeBase64Encode($key);
        $html = Http::request(array('url' => $url, 'data' => $ctxData, 'timeout' => 5 * 60, 'httpheader' => $header));
        $json = json_decode($html['html'], true);
        if(empty($json['key']))
        {
            return array();
        }
        else
        {
            if(empty($notifyUrl))
            {
                return $json;
            }
            else
            {
                return array('persistentId' => $json['persistentId']);
            }
        }
    }
}